iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 4
2
Modern Web

從LINE BOT到資料視覺化:賴田捕手系列 第 4

第 04 天:Python:資料結構與基本操作(一)

  • 分享至 

  • xImage
  •  

第 04 天:Python:資料結構與基本操作(一)

那隻草泥馬因為頭痛的關係,讓牠常常晚上睡不好覺。事實上,牠幾乎什麼狀況都有:牙痛、面皰、近視、散光、氣喘、扁平足。你多多少少會為牠感到難過的,那隻可憐的草泥馬。

~節錄自《賴田捕手》第五章

  今天我們要繼續講一些Python所提供的兩種資料型態:清單(list)跟不可變更的清單(tuple),以及相關的操作。這兩種資料型態跟昨天相比,屬於更複雜的,具有結構的資料型態。昨天講到的布林(boolean)、整數(integer)、浮點數(float)、字串(string),是 Python 中最基礎的幾樣資料型態,這些資料型態就像是磚塊,可以一塊一塊有系統、有組織的堆疊起來,變成清單。今天我們要用這些磚塊來起高樓,宴賓客了!

清單(list)及其基本操作

  大家出門逛街的時候,是否會有個習慣,先準備好一份購物清單,方便在商店裡繞得暈頭轉向的時候,低頭看看,還能夠記得這次出門需要購買的東西。或是帶著可憐的草泥馬去醫院就診之前,準備好一份病歷表,方便在醫院裡繞得暈頭轉向的時候,低頭看看,還能夠記得這次出門需要掛號的科別。大家會怎麼弄出一份方便好懂得清單呢?不外乎是['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot']吧?其實在Python裡面,創造一份清單(list)類型的物件,也是用相同的做法喔!

In [1]: medical_list = ['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot']
        type(medical_list)
Out[1]: list

  另外,也可以透過將其他類型的物件清單化的方式,來創造出新的清單物件。方法想必大家都不陌生,就是用list()。不過,可以數(ˇ)數(ˋ)的物件才能做成清單,因此丟進list()的物件,必須要可以數(ˇ)數(ˋ)。大家還記得我們學過哪些可以數(ˇ)數(ˋ)的物件嗎?

In [2]: list('123')
Out[2]: ['1', '2', '3']

  如果不是可以數(ˇ)數(ˋ)的物件:

In [3]: list(123)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-1c325c17b3d1> in <module>
----> 1 list(123)

TypeError: 'int' object is not iterable

  有了清單之後,想要查看清單中項目的數量,可以像字串一樣,用len()。如果我們想知道清單中位置在第 x 的項目,怎麼做呢?想必大家都很清楚了。如果想知道清單中,從位置在第 x 的項目開始,到位置在第 y 的項目為止,每隔 z 個項目取一個,該怎麼做呢?想必大家也都很清楚了,就代公式嘛![開始的x:結束的y:間隔的z]

In [4]: print('Length of list\t:', len(medical_list))
        print('[0]\t\t:', medical_list[0])
        print('[1:5:3]\t\t:', medical_list[1:5:3])
        Length of list	: 6
        [0]     		: toothache
        [1:5:3]	    	: ['pimple', 'asthma']

  當我拿右手著這份病歷表,左手牽著草泥馬艾克莉在醫院裡翹首四顧之時,我的合作夥伴拿著另一份清單來找我,說他一直忘了告訴我,其實可憐的艾克莉身體最近又出了一些小狀況。
  「頭暈,噁心,想吐」他無奈的拍拍艾克莉的頭,要我試著找醫生也幫忙看看這些毛病。好吧,看來我得增加一些項目到我的清單上了。怎麼做呢?我們有三種方式:

  • append()把項目一個一個放到清單中
In [5]: medical_list = ['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot']
        medical_list.append('headache')
        medical_list.append('nausea')
        medical_list.append('vomitting')
        medical_list
Out[5]: ['toothache',
         'pimple',
         'myopia',
         'astigmatism',
         'asthma',
         'flatfloot',
         'headache',
         'nausea',
         'vomitting']
  • extend()把兩個清單合併在一起
In [6]: medical_list = ['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot']
        recent_illness = ['headache', 'nausea', 'vomitting']
        medical_list.extend(recent_illness)
        medical_list
Out[6]: ['toothache',
         'pimple',
         'myopia',
         'astigmatism',
         'asthma',
         'flatfloot',
         'headache',
         'nausea',
         'vomitting']
  • 或是用+把兩個清單加在一起
In [7]: medical_list = ['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot']
        recent_illness = ['headache', 'nausea', 'vomitting']
        medical_list = medical_list + recent_illness
        medical_list
Out[7]: ['toothache',
         'pimple',
         'myopia',
         'astigmatism',
         'asthma',
         'flatfloot',
         'headache',
         'nausea',
         'vomitting']

  大家稍微注意一下上面第 3 行程式碼:medical_list = medical_list + recent_illness。事實上,在程式裡面,會常常用到這種操作,也就是我的錢 = 我的錢 + 你的錢。Python為了讓大家打字方便一點,允許把這種敘述簡化為我的錢 += 你的錢。任何運算符號都可以用這種操作。因此上面的程式碼又可以寫成:

In [8]: medical_list = ['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot']
        recent_illness = ['headache', 'nausea', 'vomitting']
        medical_list += recent_illness  # 我改了這行
        medical_list
Out[8]: ['toothache',
         'pimple',
         'myopia',
         'astigmatism',
         'asthma',
         'flatfloot',
         'headache',
         'nausea',
         'vomitting']

  更多的例子:

In [9]: 底數 = 2
        對數 = 10
        底數 **= 對數
        底數  # 已經不是底數的底數
Out[9]: 1024

  上面那段程式碼,我又偷偷加了一些新東西:井字號(#)。井字號是用來記錄註解的方法。井字號後面的東西,不會被當成程式碼,所以不會影響程式的運作。

  我看著手上又增加了3個項目的看診清單,心中不禁暗暗咒罵,我的合作夥伴居然犯了一個低級錯誤:他拼錯字了。'vomiting'而不是'vomitting'。看仔細了,中間只有一個t。好吧,看來得稍微改一下這個清單了。怎麼做呢?其實很簡單,就把清單中原本代表'vomitting'這個錯字的位置,重新指定給正確的'vomiting'就行了。我用眼睛看知道'vomitting'在清單中的位置,Python用index()知道'vomitting'在清單中的位置。

In [10]: medical_list = ['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot', 'headache', 'nausea', 'vomitting']
         print('vomitting 的位置:', medical_list.index('vomitting'))
         medical_list[(medical_list.index('vomitting'))] = 'vomiting'
         print('拼字正確的清單', medical_list)
         vomitting 的位置: 8
         拼字正確的清單 ['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot', 'headache', 'nausea', 'vomiting']

  這邊我故意把程式碼寫得繞口一點,大家可以慢慢看,訓練一下對程式碼的理解能力。
  好不容易,我把看診清單更新過了,馬不停蹄的掛了號,坐在醫院的休息區,忐忑不安地等候看診。終於有一個門診叫號叫到艾克莉了,是要幫忙看'pimple'的醫生。進去診間,醫生向我詢問了艾克莉的狀況,煞有介事的點點頭,用瞳孔筆對著艾克莉的眼睛照了照,低頭寫了幾行字,開了個藥方,告訴我只要讓艾克莉早睡早起,調整生活習慣,很快就不會有問題了。我鬆了一口氣,低頭看了看手上的看診清單,想把'pimple'從清單中劃掉,留下還需要等候看診的。該怎麼做呢?
  首先,介紹一個比較麻煩的方法,pop()pop()會將清單中最後一個項目1. 拿出來2. 給你看。舉個例子來看:

In [11]: medical_list = ['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot', 'headache', 'nausea', 'vomiting']
         print('2. 給你看', medical_list.pop())
         print('1. 拿出來', medical_list)
         2. 給你看 vomiting
         1. 拿出來 ['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot', 'headache', 'nausea']

  因為已經拿出來給你看了,所以我們的清單就少了'vomiting'這個項目了。等等,我要拿出來的不是'vomiting'吧?
  pop()在沒有預設變數的情況下,會默認你要輸入的程式碼是pop(-1),認為你有興趣的是最後一個項目,因此把最後一個項目拿出來給你看。那要怎麼拿出'pimple'而不是'vomiting'呢?很簡單,在pop()中輸入'pimple'的位置就行啦。再一次,我用眼睛看知道'pimple'的位置。Python用index()看知道'pimple'的位置。

In [12]: medical_list = ['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot', 'headache', 'nausea', 'vomiting']
         print('pimple的位置', medical_list.index('pimple'))
         print('拿出來給你看', medical_list.pop(medical_list.index('pimple')))
         print(medical_list)
         pimple的位置 1
         拿出來給你看 pimple
         ['toothache', 'myopia', 'astigmatism', 'asthma', 'flatfloot', 'headache', 'nausea', 'vomiting']

  太好了,醫生說艾克莉的'pimple'問題不是太嚴重呢!
  殘酷的現實:其實清單還有更多的操作可以玩,我就先把這些放到表一去了,有興趣的可以自己再研究研究!

表一、常用的清單(list)操作方式➀

語法 效果
list.extend()或 += 合併list
list.insert() 在指定位置插入元素,如果位置超過最大長度則放在最後面,故不會飛到很遠去或出錯。
del Object 用來刪除某個位置的元素,剩餘元素會自動往前補填補
list.remove() 用來移除指定元素
list.pop() 為類似剪出的效果,可以將指定位置的元素剪出來,預設index為 -1
list.index() 找查指定元素第一次出現的index
in Object 判斷指定元素是否存在
list.count() 計算指定元素出現次數

不可變更的清單(tuple)

  Python提供另外一種不能變更的清單,叫做tuple。要創造tuple很簡單,把項目一個一個列出來,中間用逗號(,)隔開就成了一個tuple。為了閱讀方便,習慣上也可以在前後用()將所有項目包在一起。

In [13]: medical_tuple = ('toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot', 'headache', 'nausea', 'vomitting')
         type(medical_tuple)
Out[13]: tuple

  舉一反三,我們也可以用tuple()從可以數數的物件中創造出不可變更的清單:

In [14]: medical_list = ['toothache', 'pimple', 'myopia', 'astigmatism', 'asthma', 'flatfloot', 'headache', 'nausea', 'vomitting']
         medical_tuple = tuple(medical_list)
         medical_tuple
         ('toothache',
          'pimple',
          'myopia',
          'astigmatism',
          'asthma',
          'flatfloot',
          'headache',
          'nausea',
          'vomitting')

  我們一樣可以用[x]選擇位置在第 x 的項目,一樣可以用[x:y:z]去對tuple做取樣的動作,但是這次我們就沒辦法更改裡面的項目了。

In [15]: medical_tuple[-1]
Out[15]: 'vomitting'

  咦?vomitting?

In [16]: medical_tuple[-1] = 'vomiting'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-14-76f9e11e8084> in <module>
----> 1 medical_tuple[-1] = 'vomiting'

TypeError: 'tuple' object does not support item assignment

  慘了拼錯字了。

  今天關於Python的物件類型就先介紹到這裡,明天會繼續來介紹更多精彩的物件類型。一樣,今天文章中的程式碼範例都有放在 Github 上(Githubnbviewer),有興趣的或我沒講清楚的,可以試著下載下來玩玩看!謝謝大家!

Introducing Python、Introducing Python 閱讀筆記第三章

註:對於此系列文有興趣的讀者,歡迎參考由此系列文擴編成書的 LINE Bot by Python,以及最新的系列文《賴田捕手:追加篇》
第 31 天 初始化 LINE BOT on Heroku
第 32 天 快速回覆 QuickReply 介紹
第 33 天 妥善運用 Heroku APP 暫存空間
第 34 天 妥善運用 LINE Notify 免費推播
第 35 天 製造 Deploy to Heroku 按鈕


上一篇
第 03 天:Python:資料型態與基本操作
下一篇
第 05 天:Python:資料結構與基本操作(二)
系列文
從LINE BOT到資料視覺化:賴田捕手30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
jerry_180801
iT邦新手 5 級 ‧ 2020-04-09 20:19:51

辛勤的草泥馬們,晚上好~
又到了工作之餘的學習時間,感覺自己就像個問題學生...
也請作者多多包涵>"<a 真的找不到身邊的親朋好友解答我的疑惑...

進入正題XD,每一篇對我來說都是珍寶,除了複製貼上之外,自己也很希望能親自參與,所以我寫了很小一段程式碼..但不懂它的回覆為何如此?
學習過程中,我明白[起始:結束]是從起始開始但不包含結束,而[::]是從一而終的用法,但應也不包含結束。

程式碼如下:
fruit = ['apple', 'banana','pineapple', 'orange', 'grape', 'watermelon', 'strawberry']
#print(type(fruit))
print('水果種類有幾種?\t', len(fruit), '種')
#print('第1種水果是什麼?\t', fruit[0])
print(fruit.index('apple'), fruit.index('strawberry'))
print(fruit[0], fruit[6])
print('水果_list:', fruit[fruit.index('apple'):fruit.index('strawberry'):3])
print('水果_list_1:', fruit[::3])

水果種類有幾種? 7 種
0 6
apple strawberry
水果_list: ['apple', 'orange']
水果_list_1: ['apple', 'orange', 'strawberry']

得到這結果,讓我思考兩天...........
還請草泥馬們,幫幫忙解惑>Q<a
還是我對[]的理解還是有問題的0.0?

您好:

比較讓您感到疑惑的,應該是

print('水果_list:', fruit[fruit.index('apple'):fruit.index('strawberry'):3])
print('水果_list_1:', fruit[::3])

這兩個切片的差別吧?

沒問題,讓我們再來一遍:

In [1]: 排好的數字 = "0123456789"
        開始 = 0
        結束 = 10
        間隔 = 3
        print("A.", 排好的數字[開始:結束:間隔])
Out[1]: A. 0369

因為 python 總是從零開始,所以當我們的切片開始為0的時候,可以不特別指定:

In [2]: 排好的數字 = "0123456789"
        結束 = 10
        間隔 = 3
        print("B.", 排好的數字[:結束:間隔])
Out[2]: B. 0369

當我們不特別指定結束的時候,得到的結果如下:

In [3]: 排好的數字 = "0123456789"
        間隔 = 3
        print("C.", 排好的數字[::間隔])
Out[3]: C. 0369

意思是,當我們不特別指定結束的時候,python 會認為我們想要的結束是10。而不是9。為什麼是10呢?這個數字哪裡來的呢?

In [4]: 排好的數字 = "0123456789"
        結束 = len(排好的數字)
        間隔 = 3
        print("D.", 排好的數字[:結束:間隔])
Out[4]: D. 0369

若用的是9,還記得 python 切片的原則,包含開始的 (此例為0),不包含結束的 (此例為9):

In [5]: 排好的數字 = '0123456789'
        結束 = 排好的數字.index('9')
        間隔 = 3
        print("E.", 排好的數字[:結束:間隔])
Out[5]: E. 036

所以,當我們什麼都不指定的時候,python 會認為我們的切片要切到最後 (len(排好的數字)),而不是只到9而已喔。

另外,最近也看到心原一馬大大關於切片的教學文,覺得挺不錯的,也供您參考看看囉!

我要留言

立即登入留言